package com.chen.pfm.slice;

import com.chen.pfm.ResourceTable;
import com.chen.pfm.entity.Account;
import com.chen.pfm.entity.Classify;
import com.chen.pfm.entity.DisplayBill;
import com.chen.pfm.entity.ResultVo;
import com.chen.pfm.provider.ClassifyProvider;
import com.chen.pfm.provider.TitleProvider;
import com.chen.pfm.utils.*;
import com.google.gson.Gson;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.ability.DataAbilityRemoteException;
import ohos.aafwk.content.Intent;
import ohos.agp.components.*;
import ohos.agp.utils.LayoutAlignment;
import ohos.agp.window.dialog.CommonDialog;
import ohos.agp.window.dialog.ListDialog;
import ohos.app.AbilityContext;
import ohos.app.dispatcher.task.TaskPriority;
import ohos.hiviewdfx.HiLog;
import ohos.hiviewdfx.HiLogLabel;
import okhttp3.FormBody;
import okhttp3.RequestBody;

import javax.lang.model.element.VariableElement;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import static ohos.agp.components.ComponentContainer.LayoutConfig.MATCH_CONTENT;

public class BillDetailsSlice extends AbilitySlice {
    static final HiLogLabel LABEL = new HiLogLabel(HiLog.LOG_APP, 0x2022001, "BillDetailsSlice");
    DisplayBill displayBill;
    Button submit; //提交按钮
    Button delete;//删除按钮
    Text billDetails_Aid;   //账单id
    TextField billDetails_Amoney; //价格
    Text billDetails_Cid;  //分类id
    Text billDetails_type1; //分类类型
    Text billDetails_cname;//分类名
    Text billDetails_rtime; //记录账单日期
    Text billDetails_ctime; //创建时间
    Text billDetails_aremark;//备注

    boolean isUpdateAmoney = false;
    boolean isUpdateCid = false;
    boolean isUpdateRtime = false;
    boolean isUpdateAremark = false;

    DirectionalLayout layout_billDetails_type1;
    DirectionalLayout layout_billDetails_cname;
    DirectionalLayout layout_billDetails_rtime;
    DirectionalLayout layout_billDetails_aremark;
    String newAremark;//新备注
    String newCid;//新分类
    String newArtime;//新记录时间

    //日期  年-月-日，时-分-秒
    private int dateYear, dateMonth, dateDay;
    List<Classify> classifies_expenditure;//花费
    List<Classify> classifies_income;//收入
    List<Classify> classifies_property;//资产
    ClassifyProvider classifyProvider;//数据适配器
    Classify item;
    //账单类型
    private int accountsType = 0; //0表示支出，1表示收入,2资产

    String aid;

    @Override
    protected void onStart(Intent intent) {
        super.onStart(intent);
        aid = intent.getStringParam("Aid");

        setUIContent(ResourceTable.Layout_ability_displaybill_detail);
        //返回按钮监听
        findComponentById(ResourceTable.Id_goback_btn).setClickedListener(component -> terminate());

        if (aid == null) {
            MyToast.showMyToast(this, "账单id获取错误！");
            HiLog.error(LABEL, "账单id获取错误");
            return;
        }
        try {
            displayBill = MyUtil.queryDisplayBillByAid(this, aid);
        } catch (DataAbilityRemoteException e) {
            e.printStackTrace();
        }
        if (displayBill == null) {
            MyToast.showMyToast(this, "账单对象获取错误！");
            HiLog.error(LABEL, "账单对象获取错误");
            return;
        }
        //提交按钮
        submit = (Button) findComponentById(ResourceTable.Id_submit);
        submit.setClickedListener(component -> saveData(component));
        //删除按钮
        delete = (Button) findComponentById(ResourceTable.Id_delete);
        delete.setClickedListener(component -> deleteData(component));
        //账单信息获取
        //账单id
        billDetails_Aid = (Text) findComponentById(ResourceTable.Id_billDetails_Aid);
        //价格
        billDetails_Amoney = (TextField) findComponentById(ResourceTable.Id_billDetails_Amoney);
        //分类id
        billDetails_Cid = (Text) findComponentById(ResourceTable.Id_billDetails_Cid);
        //分类类型
        billDetails_type1 = (Text) findComponentById(ResourceTable.Id_billDetails_type1);
        //分类名
        billDetails_cname = (Text) findComponentById(ResourceTable.Id_billDetails_cname);
        //记录账单日期
        billDetails_rtime = (Text) findComponentById(ResourceTable.Id_billDetails_rtime);
        //创建时间
        billDetails_ctime = (Text) findComponentById(ResourceTable.Id_billDetails_ctime);
        //备注
        billDetails_aremark = (Text) findComponentById(ResourceTable.Id_billDetails_aremark);

        layout_billDetails_type1 = (DirectionalLayout) findComponentById(ResourceTable.Id_layout_billDetails_type1);
        layout_billDetails_cname = (DirectionalLayout) findComponentById(ResourceTable.Id_layout_billDetails_cname);
        layout_billDetails_aremark = (DirectionalLayout) findComponentById(ResourceTable.Id_layout_billDetails_aremark);
        layout_billDetails_rtime = (DirectionalLayout) findComponentById(ResourceTable.Id_layout_billDetails_rtime);


        //渲染数据
        billDetails_Aid.setText(displayBill.getAid());
        billDetails_Amoney.setText(MyUtil.getStrBalance(displayBill.getAmoney()));
        billDetails_Cid.setText(displayBill.getCid());
        newCid = displayBill.getCid();

        if (displayBill.getType1() == 1) {
            billDetails_type1.setText("支出");
        } else if (displayBill.getType1() == 2) {
            billDetails_type1.setText("收入");
        } else {
            billDetails_type1.setText("资产");
        }
        billDetails_cname.setText(displayBill.getCname());
        billDetails_rtime.setText(DateUtils.getChineseFormatFromStr(displayBill.getRecordTime()));
        newArtime = displayBill.getRecordTime();
        billDetails_ctime.setText(displayBill.getCreatTime());
        billDetails_aremark.setText(displayBill.getAremark());
        newAremark = displayBill.getAremark();

        //访问本地数据库
        //加载数据
        try {
            classifies_expenditure = ClassifyDBUtil.queryAllClassifyByCtype1(this, 1);
            classifies_income = ClassifyDBUtil.queryAllClassifyByCtype1(this, 2);
            classifies_property = ClassifyDBUtil.queryAllClassifyByCtype1(this, 3);
        } catch (DataAbilityRemoteException e) {
            e.printStackTrace();
        }

        //按键监听

        //账单类型
        layout_billDetails_type1.setClickedListener(component -> {
            showPickBillDetailsClassifyType(this);
        });
        //账单类型
        layout_billDetails_cname.setClickedListener(component -> {
            showPickAccountsTypeClass(this);
        });
        //记录账单日期
        layout_billDetails_rtime.setClickedListener(component -> {
            showPickDateConfirmTips(this);
        });
        //账单备注
        layout_billDetails_aremark.setClickedListener(component -> {
            setBillDetailsAremark(this);
        });
    }

    private void saveData(Component component) {
        String money = billDetails_Amoney.getText();
        if (money == null || "".equals(money)) {
            MyToast.showMyToast(this, "金额输入为空!");
            return;
        } else if (!MyUtil.isMoneyNumber(money)) {
            MyToast.showMyToast(this, "金额输入不合法!");
            return;
        } else {
            if (!money.equals(MyUtil.getStrBalance(displayBill.getAmoney()))) {
                isUpdateAmoney = true;
            }
        }
        if (!isUpdateAmoney && !isUpdateRtime && !isUpdateAremark && !isUpdateCid) {
            MyToast.showMyToast(this, "你还没更改信息!");
            return;
        }

        HiLog.info(LABEL, "isUpdateAmoney=" + isUpdateAmoney + "isUpdateRtime=" + isUpdateRtime + "isUpdateAremark=" + isUpdateAremark + "isUpdateCid=" + isUpdateCid);
        //不变的
        Account account = new Account();
        account.setAid(displayBill.getAid());
        String uid = DataBaseUtil.GetValue(this, "uid");
        if (uid == null) {
            MyToast.showMyToast(this, "用户uid为空，无法更新!");
            return;
        }
        account.setUid(Integer.valueOf(uid));
        account.setActime(displayBill.getCreatTime());
        //会变的
        account.setAmoney(MyUtil.getDoubleBalancefromStr(money));
        account.setCid(newCid);

        account.setAremark(newAremark);
        account.setArtime(newArtime);

        HiLog.info(LABEL, "" + account.toString());

        try {
            int update = AccountDBUtil.updateAccount(this, account);
            if (update > 0) {
                MyToast.showMyToast(this, "本地账单更新成功！");
                //开一个线程更新信息
                updateRemoteAccountData(account);
            }
        } catch (DataAbilityRemoteException e) {
            e.printStackTrace();
        }

    }

    private void deleteData(Component component) {


        try {
            int del = AccountDBUtil.deleteAccountByAid(this, aid);
            if (del > 0) {
                MyToast.showMyToast(this, "本地账单删除成功！");
                //开一个线程更新信息
                delRemoteAccountData(aid);
            }
        } catch (DataAbilityRemoteException e) {
            e.printStackTrace();
        }

    }

    private void delRemoteAccountData(String aid) {
        getGlobalTaskDispatcher(TaskPriority.DEFAULT).asyncDispatch(() -> {
            ResultVo resultVo;
            String url = MyUtil.ngrokUri + "/account/deleteAccountByid";
            String getRequestjson = null;
            RequestBody requestBody = new FormBody.Builder()
                    .add("aid", aid)
                    .build();
            Gson gson = new Gson();
            //转化为json
            try {
                getRequestjson = HttpRequestUtil.sendPostRequestByOkHttp(url, requestBody);
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (getRequestjson == null || getRequestjson.contains("not found")) {
                HiLog.info(LABEL, "无法连接到网络！");
                //刷新页面上的数据，同样有一个坑，onChange方法实质上，在一个子线程里执行
                getUITaskDispatcher().asyncDispatch(() -> {
                            //在这里执行页面ui组件的显示刷新
                            MyToast.showMyToast(this, "无法连接到网络");
                        }
                );
                return;
            } else {
                try {
                    resultVo = gson.fromJson(getRequestjson, ResultVo.class);
                } catch (Exception e) {
                    getUITaskDispatcher().asyncDispatch(() -> {
                        MyToast.showMyToast(this, "gson解析返回对象失败，请确定服务器是否开启");
                    });
                    HiLog.error(LABEL, "有网络但是连接不到服务器时返回数据为：" + getRequestjson);
                    return;
                }

                if (resultVo == null) {//返回对象进行解析
                    HiLog.info(LABEL, "返回对象为空！");
                    //刷新页面上的数据，同样有一个坑，onChange方法实质上，在一个子线程里执行
                    getUITaskDispatcher().asyncDispatch(() -> {
                        //在这里执行页面ui组件的显示刷新
                        MyToast.showMyToast(this, "返回为空,数据丢失！");
                    });
                    return;
                } else if (resultVo.getCode() == 200) {
                    getUITaskDispatcher().asyncDispatch(() -> {
                        //在这里执行页面ui组件的显示刷新
                        MyToast.showMyToast(this, "状态码 200 " + resultVo.getMsg());
                        Intent intent = new Intent();
                        intent.setParam("op", "del");
                        intent.setParam("aid", displayBill.getAid());
                        setResult(intent);
                        terminate();
                    });
                } else if (resultVo.getCode() == 404) {
                    getUITaskDispatcher().asyncDispatch(() -> {
                        //在这里执行页面ui组件的显示刷新
                        MyToast.showMyToast(this, "状态码 404 " + resultVo.getMsg());

                    });
                }

            }


        });

    }

    private void updateRemoteAccountData(Account account) {
        getGlobalTaskDispatcher(TaskPriority.DEFAULT).asyncDispatch(() -> {
            ResultVo resultVo;
            String url = MyUtil.ngrokUri + "/account/updateAccountByAid";
            String getRequestjson = null;
            Gson gson = new Gson();
            //转化为json
            String sendjson = gson.toJson(account);

            try {
                getRequestjson = HttpRequestUtil.sendPostRequestByOkHttp(url, sendjson);
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (getRequestjson == null || getRequestjson.contains("not found")) {
                HiLog.info(LABEL, "无法连接到网络！");
                //刷新页面上的数据，同样有一个坑，onChange方法实质上，在一个子线程里执行
                getUITaskDispatcher().asyncDispatch(() -> {
                            //在这里执行页面ui组件的显示刷新
                            MyToast.showMyToast(this, "无法连接到网络");
                        }
                );
                return;
            } else {
                try {
                    resultVo = gson.fromJson(getRequestjson, ResultVo.class);
                } catch (Exception e) {
                    getUITaskDispatcher().asyncDispatch(() -> {
                        MyToast.showMyToast(this, "gson解析返回对象失败，请确定服务器是否开启");
                    });
                    HiLog.error(LABEL, "有网络但是连接不到服务器时返回数据为：" + getRequestjson);
                    return;
                }

                if (resultVo == null) {//返回对象进行解析
                    HiLog.info(LABEL, "返回对象为空！");
                    //刷新页面上的数据，同样有一个坑，onChange方法实质上，在一个子线程里执行
                    getUITaskDispatcher().asyncDispatch(() -> {
                        //在这里执行页面ui组件的显示刷新
                        MyToast.showMyToast(this, "返回为空,数据丢失！");
                    });
                    return;
                } else  {
                    getUITaskDispatcher().asyncDispatch(() -> {
                        //在这里执行页面ui组件的显示刷新
                        MyToast.showMyToast(this, "状态码 "+resultVo.getCode()+" " + resultVo.getMsg());
                        if(resultVo.getCode()==200){
                            HiLog.info(LABEL, "本地数据库创建成功！");
                            Intent intent = new Intent();
                            intent.setParam("op", "update");
                            intent.setParam("aid", displayBill.getAid());
                            setResult(intent);
                            //   关闭当前Ability
                            terminate();
                        }

                    });
                }

            }


        });

    }

    public void showPickBillDetailsClassifyType(AbilityContext context) {
        ListDialog listDialog = new ListDialog(context, ListDialog.SINGLE);
        listDialog.setCornerRadius(45);
        listDialog.setSize(800, MATCH_CONTENT);
        String[] strings = {"支出", "收入", "资产"};
        List<String> titles = new ArrayList<>();
        titles.add("支出");
        titles.add("收入");
        titles.add("资产");
        listDialog.setItems(strings);
        TitleProvider titleProvider = new TitleProvider(titles, this);
        listDialog.setProvider(titleProvider);
        listDialog.setButton(0, "取消", (iDialog, i) -> {
            iDialog.hide();
            MyToast.showMyToast(this, "已取消");

        });
        listDialog.setButton(1, "确定", (iDialog, i) -> {
            iDialog.hide();
            MyToast.showMyToast(this, "已确定");
        });
        //展示
        listDialog.show();
        //监听
        ((ListContainer) listDialog.getListContainer()).setItemSelectedListener((listContainer, component, i, l) -> {
            MyToast.showMyToast(this, "你选择了" + strings[i]);
            billDetails_type1.setText(strings[i]);
            accountsType = i;
            listDialog.hide();
        });
    }

    //弹出日期dialog，选择日期
    public void showPickDateConfirmTips(AbilityContext context) {
        CommonDialog commonDialog = new CommonDialog(context);
        Component parse = LayoutScatter.getInstance(context)
                .parse(ResourceTable.Layout_dialog_date_layout_confirm, null, false);
        DatePicker datePicker = (DatePicker) parse.findComponentById(ResourceTable.Id_date_pick);
        //取消按钮
        Button cancel = (Button) parse.findComponentById(ResourceTable.Id_cancel);
        //确定按钮
        Button ok = (Button) parse.findComponentById(ResourceTable.Id_ok);
        cancel.setClickedListener(c -> {
            commonDialog.destroy();
            MyToast.showMyToast(this, "已取消");

        });
        ok.setClickedListener(c -> {
            dateYear = datePicker.getYear();
            dateMonth = datePicker.getMonth();
            dateDay = datePicker.getDayOfMonth();
            isUpdateRtime = true;
            newArtime = DateUtils.getStrDecimalFormatDate(dateYear, dateMonth, dateDay, 0, 0, 0);
            billDetails_rtime.setText(DateUtils.getChineseFormatFromPicker(dateYear, dateMonth, dateDay));
            commonDialog.remove();
        });
        commonDialog.setSize(MATCH_CONTENT, MATCH_CONTENT);
        commonDialog.setAlignment(LayoutAlignment.CENTER);
        commonDialog.setTransparent(true);
        commonDialog.setCornerRadius(25);
        commonDialog.setContentCustomComponent(parse);
        commonDialog.show();
    }

    private void showPickAccountsTypeClass(AbilityContext context) {

        Component parse = LayoutScatter.getInstance(this).parse(ResourceTable.Layout_dialog_accountstype_select, null, false);
        ListContainer accountTypelistContainer = (ListContainer) parse.findComponentById(ResourceTable.Id_accountType_listContainer);

        //创建显示气窗
        CommonDialog dialog = new CommonDialog(this);
        dialog.setOffset(0, 10);
        dialog.setContentCustomComponent(parse);
        dialog.setSize(MATCH_CONTENT, MATCH_CONTENT);
        //取消按钮
        Button cancel = (Button) parse.findComponentById(ResourceTable.Id_cancel);

        if (accountsType == 0) {
            //装载数据,不能合并写，后面需要逆转换
            classifyProvider = new ClassifyProvider(classifies_expenditure, this);
            accountTypelistContainer.setItemProvider(classifyProvider);
        } else if (accountsType == 1) {

            //装载数据
            classifyProvider = new ClassifyProvider(classifies_income, this);
            accountTypelistContainer.setItemProvider(classifyProvider);
        } else if (accountsType == 2) {
            //装载数据
            classifyProvider = new ClassifyProvider(classifies_property, this);
            accountTypelistContainer.setItemProvider(classifyProvider);
        }

        cancel.setClickedListener(c -> {
            dialog.hide();
            MyToast.showMyToast(this, "已取消");

        });
        dialog.show();
        accountTypelistContainer.setItemSelectedListener(new ListContainer.ItemSelectedListener() {
            @Override
            public void onItemSelected(ListContainer listContainer, Component component, int i, long l) {
                component.setClickedListener(component1 -> {
                });
                item = (Classify) classifyProvider.getItem(i);
                if (item == null) {
                    MyToast.showMyToast(getContext(), "列表项分类对象逆转失败");
                    HiLog.error(LABEL, "列表项分类对象逆转失败" + item);
                    return;
                }
                MyToast.showMyToast(getContext(), "你选择了 " + item.getCname());
                //设置分类名字
                billDetails_cname.setText(item.getCname());
                newCid = item.getCid();
                if (!newCid.equals(displayBill.getCid())) {
                    isUpdateCid = true;
                }
                dialog.destroy();
            }
        });


    }


    private void setBillDetailsAremark(AbilityContext context) {
        //布局加载
        Component parse = LayoutScatter.getInstance(this).parse(ResourceTable.Layout_dialog_remark_layout_input, null, false);
        //创建显示气窗
        CommonDialog dialog = new CommonDialog(this);
        dialog.setOffset(0, 10);
        dialog.setContentCustomComponent(parse);
        dialog.setSize(MATCH_CONTENT, MATCH_CONTENT);
        //取消按钮
        Button cancel = (Button) parse.findComponentById(ResourceTable.Id_cancel);
        //确定按钮
        Button ok = (Button) parse.findComponentById(ResourceTable.Id_ok);
        //预算设置的输入框
        TextField textField = (TextField) parse.findComponentById(ResourceTable.Id_TextField);
        //显示原来的
        textField.setText(billDetails_aremark.getText());
        //ui刷新线程显示
        getUITaskDispatcher().asyncDispatch(() -> {
            dialog.show();
            cancel.setClickedListener(c -> {
                dialog.destroy();
                MyToast.showMyToast(this, "已取消");

            });
            ok.setClickedListener(c -> {
                String Aremark = textField.getText();
                if (!displayBill.getAremark().equals(Aremark)) {
                    isUpdateAremark = true;
                    //刷新备注内容
                    newAremark = Aremark;
                    billDetails_aremark.setText(Aremark);
                }

                dialog.hide();

            });
        });
    }
}
